home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
upc12bs2.zip
/
RNEWS
/
expire.c
next >
Wrap
C/C++ Source or Header
|
1993-07-12
|
20KB
|
540 lines
/*--------------------------------------------------------------------*/
/* e x p i r e . c */
/* */
/* Expire old news articles for UUPC/extended */
/* */
/* Copyright (c) 1992-1993 by Kendra Electronic Wonderworks, all */
/* rights reserved except those explicitly granted by the UUPC/ */
/* extended license. */
/*--------------------------------------------------------------------*/
/*
* $Id: expire.c 1.5 1993/07/13 01:13:32 ahd Exp $
*
* $Log: expire.c $
* Revision 1.5 1993/07/13 01:13:32 ahd
* Drop unused stater.h header
*
* Revision 1.4 1993/04/05 04:32:19 ahd
* Add timestamp, size to information returned by directory searches
*
* Revision 1.3 1992/11/25 12:59:17 ahd
* Modifiy summery messages
*
*/
/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <limits.h>
/*--------------------------------------------------------------------*/
/* UUPC/extended include files */
/*--------------------------------------------------------------------*/
#include "lib.h"
#include "active.h"
#include "dater.h"
#include "getopt.h"
#include "hlib.h"
#include "import.h"
#include "importng.h"
#include "logger.h"
#include "uundir.h"
#include "pushpop.h"
#include "timestmp.h"
currentfile();
/*--------------------------------------------------------------------*/
/* Global Variables */
/*--------------------------------------------------------------------*/
#define ONE_DAY (60L*60L*24L)
/*--------------------------------------------------------------------*/
/* Internal prototypes */
/*--------------------------------------------------------------------*/
static boolean numeric( char *start);
static void ExpireAll( const time_t expire_date,
const time_t archive_date );
static void ExpireGroup( const char *group,
const time_t expire_date,
const time_t archive_date );
static void ExpireOneGroup( struct grp *cur_grp,
const time_t expire_date,
const time_t archive_date );
static void ExpireDirectory( struct grp *cur_grp,
const time_t expire_date,
const char *directory,
const char *archive );
static boolean numeric( char *start);
static void usage( void );
long total_articles_purged = 0;
long total_articles_archived = 0;
long total_articles_kept = 0;
long total_bytes_purged = 0;
long total_bytes_archived = 0;
long total_bytes_kept = 0;
/*--------------------------------------------------------------------*/
/* m a i n */
/* */
/* Main program */
/*--------------------------------------------------------------------*/
void main( int argc, char **argv)
{
int c;
extern char *optarg;
extern int optind;
char *group = NULL;
time_t expire_period = 7; /* Seven days visible to users */
time_t archive_period = 0; /* Seven days after expiring in arch */
time_t expire_date;
time_t archive_date;
/*--------------------------------------------------------------------*/
/* Report our version number and date/time compiled */
/*--------------------------------------------------------------------*/
debuglevel = 1;
banner( argv );
#if defined(__CORE__)
copywrong = strdup(copyright);
checkref(copywrong);
#endif
/*--------------------------------------------------------------------*/
/* Process our arguments */
/*--------------------------------------------------------------------*/
while ((c = getopt(argc, argv, "e:a:g:x:n:")) != EOF)
switch(c) {
case 'a':
archive_period = atoi( optarg );
break;
case 'e':
expire_period = atoi( optarg );
break;
case 'n':
group = optarg;
break;
case 'x':
debuglevel = atoi( optarg );
break;
case '?':
usage();
exit(1);
break;
default:
printmsg(0, "expire - invalid option -%c", c);
usage();
exit(2);
break;
}
if (optind != argc) {
fputs("Extra parameter(s) at end.\n", stderr);
usage();
exit(2);
}
/*--------------------------------------------------------------------*/
/* Initialize */
/*--------------------------------------------------------------------*/
tzset(); /* Set up time zone information */
if (!configure( B_NEWS ))
exit(1); /* system configuration failed */
/*--------------------------------------------------------------------*/
/* Switch to the spooling directory */
/*--------------------------------------------------------------------*/
PushDir( E_newsdir );
atexit( PopDir );
/*--------------------------------------------------------------------*/
/* Initialize logging file */
/*--------------------------------------------------------------------*/
openlog( NULL );
/*--------------------------------------------------------------------*/
/* Load the active file */
/*--------------------------------------------------------------------*/
get_active(); /* Get sequence numbers for groups from
active file */
/*--------------------------------------------------------------------*/
/* Compute times for expiring files */
/*--------------------------------------------------------------------*/
time( &expire_date );
expire_date -= (expire_period * ONE_DAY);
archive_date = expire_date - (archive_period * ONE_DAY);
printmsg(1,"%s: %sing news older than %s (%ld days)",
argv[0],
archive_period ? "Archiv" : "Purg",
dater( expire_date , NULL), (long) expire_period );
if ( archive_period != 0 )
printmsg(1,"%s: Purging news older than %s",
argv[0],
dater( archive_date , NULL));
/*--------------------------------------------------------------------*/
/* Process one group if requested, otherwise process the entire */
/* active file */
/*--------------------------------------------------------------------*/
if ( group != NULL )
ExpireGroup( group, expire_date, archive_date );
else
ExpireAll(expire_date, archive_date );
/*--------------------------------------------------------------------*/
/* Clean up and exit */
/*--------------------------------------------------------------------*/
put_active();
if ( total_articles_purged || total_articles_archived)
printmsg(1,"%s: Purged %ld total articles (%ld bytes), "
"archived %ld total articles (%ld bytes). " ,
argv[0],
total_articles_purged, total_bytes_purged,
total_articles_archived, total_bytes_archived );
printmsg(1,"%s: Left alone %ld articles (%ld bytes). "
"Total of %ld articles now use %ld bytes." ,
argv[0],
total_articles_kept, total_bytes_kept,
total_articles_kept + total_articles_archived,
total_bytes_kept + total_bytes_archived );
exit(0);
} /* main */
/*--------------------------------------------------------------------*/
/* E x p i r e A l l */
/* */
/* Expire all defined news groups */
/*--------------------------------------------------------------------*/
static void ExpireAll( const time_t expire_date,
const time_t archive_date )
{
struct grp *cur_grp = group_list;
while ( cur_grp != NULL )
{
ExpireOneGroup( cur_grp, expire_date, archive_date );
/* Clean up this group */
cur_grp = cur_grp->grp_next; /* Then clean up the next group */
}
} /* Expire_All */
/*--------------------------------------------------------------------*/
/* E x p i r e G r o u p */
/* */
/* Clean up one group by name */
/*--------------------------------------------------------------------*/
static void ExpireGroup( const char *group,
const time_t expire_date,
const time_t archive_date )
{
struct grp *cur_grp = group_list;
struct grp *target = NULL;
/*--------------------------------------------------------------------*/
/* Search the list of groups for the requested group */
/*--------------------------------------------------------------------*/
while ( (cur_grp != NULL) && (target == NULL))
{
if ( equal( cur_grp->grp_name, group ))
target = cur_grp;
cur_grp = cur_grp->grp_next; /* Then clean up the next group */
}
/*--------------------------------------------------------------------*/
/* If we found the group, process it, otherwise report the error */
/*--------------------------------------------------------------------*/
if ( target == NULL )
printmsg(0,"Unable to locate active group %s", group );
else
ExpireOneGroup( target, expire_date, archive_date );
/* Clean up this group */
} /* ExpireGroup */
/*--------------------------------------------------------------------*/
/* E x p i r e O n e G r o u p */
/* */
/* Clean up one group by name */
/*--------------------------------------------------------------------*/
static void ExpireOneGroup( struct grp *cur_grp,
const time_t expire_date,
const time_t archive_date )
{
char groupdir[FILENAME_MAX];
char archdir[FILENAME_MAX];
printmsg(3,"Processing news group %s", cur_grp->grp_name );
/*--------------------------------------------------------------------*/
/* Set up the directory names */
/*--------------------------------------------------------------------*/
ImportNewsGroup( groupdir, cur_grp->grp_name, 0 );
mkfilename( archdir, E_archivedir, &groupdir[ strlen( E_newsdir) + 1] );
/*--------------------------------------------------------------------*/
/* Process the primary and archive directories */
/*--------------------------------------------------------------------*/
ExpireDirectory( cur_grp, archive_date, archdir, NULL);
/* Purge archive first to keep
directory smaller */
ExpireDirectory( cur_grp, expire_date, groupdir,
(archive_date < expire_date) ? archdir : NULL);
/* Do not archive for 0 days! */
} /* ExpireOneGroup */
/*--------------------------------------------------------------------*/
/* E x p i r e D i r e c t o r y */
/* */
/* Clean up one group by name */
/*--------------------------------------------------------------------*/
static void ExpireDirectory( struct grp *cur_grp,
const time_t expire,
const char *directory,
const char *archive )
{
char fname[FILENAME_MAX];
int articles_archived = 0;/* Count of files moved to archive */
int articles_purged = 0;/* Count of files actually deleted */
int articles_kept = 0;/* Count of files actually deleted */
long bytes_purged = 0; /* Bytes freed on disk from deletions */
long bytes_kept = 0; /* Bytes left on disk total */
long bytes_archived = 0; /* Bytes left on disk in archive */
boolean not_built = TRUE; /* Did not insure archive directory
exists */
long low = LONG_MAX; /* Oldest article number left */
DIR *dirp;
struct direct *dp;
/*--------------------------------------------------------------------*/
/* Open up the directory for processing */
/*--------------------------------------------------------------------*/
if ((dirp = opendirx(directory,"*.*")) == nil(DIR))
{
printmsg(3, "ExpireDirectory: couldn't opendir() %s", directory);
cur_grp->grp_low = cur_grp->grp_high;
return;
} /* if */
/*--------------------------------------------------------------------*/
/* Switch to directory for processing */
/*--------------------------------------------------------------------*/
CHDIR( directory );
/*--------------------------------------------------------------------*/
/* Look for the next file in the directory */
/*--------------------------------------------------------------------*/
while((dp = readdir(dirp)) != nil(struct direct))
{
/*--------------------------------------------------------------------*/
/* Archive/expire this file? */
/*--------------------------------------------------------------------*/
if ( numeric( dp->d_name ))/* Article format name? */
{ /* Yes --> Examine it closer */
printmsg(6,"Processing file %s from %s",
dp->d_name, dater( dp->d_modified, NULL));
if ( dp->d_modified < expire ) /* Long in the tooth? */
{ /* Yes --> Move it on out */
int not_processed = TRUE;
/* Purge unless we archive it */
if ( archive != NULL )
{
printmsg( 4,"Archiving file %s from %s to %s",
dp->d_name, directory , archive);
if ( not_built ) /* First pass into directory? */
{ /* Yes --> Make sure it exists */
MKDIR( archive );
not_built = FALSE; /* Only build it once */
}
mkfilename( fname, archive, dp->d_name);
not_processed = rename( dp->d_name, fname );
if ( not_processed )
{
printerr( fname );
printmsg(0,"Rename %s to %s failed, purging file.",
dp->d_name, fname);
}
else {
articles_archived++;
bytes_archived += dp->d_size;
}
} /* if ( archive != NULL ) */
if ( not_processed )
{
printmsg( 4,"Purging file %s from %s", dp->d_name, directory );
unlink( dp->d_name );
articles_purged++;
bytes_purged += dp->d_size;
} /* if ( not_processed ) */
} /* if ( dp->d_modified < expire ) */
/*--------------------------------------------------------------------*/
/* If the article is valid and still in the main news */
/* directory, determine if it is the lowest article left */
/*--------------------------------------------------------------------*/
else {
long article = 0;
char *digit = dp->d_name;
while( *digit )
article = article * 10 + (*digit++ - '0');
low = min( article, low );
bytes_kept += dp->d_size;
articles_kept ++;
} /* else if ( archive != NULL ) */
} /* if ( numeric( dp->d_name ) */
} /* while */
/*--------------------------------------------------------------------*/
/* Update lowest article available to the users */
/*--------------------------------------------------------------------*/
if ( low == LONG_MAX )
cur_grp->grp_low = cur_grp->grp_high;
else
cur_grp->grp_low = low;
/*--------------------------------------------------------------------*/
/* Close up the directory and report what we did */
/*--------------------------------------------------------------------*/
closedir(dirp);
if ( articles_archived )
printmsg(2,"%s: Purged %d articles (%ld bytes),"
" archived %d articles (%ld bytes),"
" left alone %d articles (%ld bytes).",
cur_grp->grp_name,
articles_purged, bytes_purged,
articles_archived, bytes_archived,
articles_kept, bytes_kept );
else if ( articles_purged )
printmsg(2,"%s: Purged %d articles (%ld bytes),"
" left alone %d articles (%ld bytes).",
cur_grp->grp_name,
articles_purged, bytes_purged,
articles_kept, bytes_kept );
else if ( articles_kept )
printmsg(2,"%s: Left alone %d articles (%ld bytes).",
cur_grp->grp_name,
articles_kept, bytes_kept );
total_articles_archived += articles_archived;
total_articles_kept += articles_kept;
total_articles_purged += articles_purged;
total_bytes_archived += bytes_archived;
total_bytes_kept += bytes_kept;
total_bytes_purged += bytes_purged;
} /* ExpireDirectory */
/*--------------------------------------------------------------------*/
/* n u m e r i c */
/* */
/* Examines string, returns true if numeric with period */
/*--------------------------------------------------------------------*/
static boolean numeric( char *start)
{
char *number = start;
while (*number != '\0')
{
if (!isdigit(*number) && (*number != '.'))
return FALSE;
number++;
}
return TRUE;
} /* numeric */
/*--------------------------------------------------------------------*/
/* u s a g e */
/* */
/* Print usage of program */
/*--------------------------------------------------------------------*/
static void usage( void )
{
printf( "Usage: expire [-edays] [-adays] [-ngroup]\n");
exit(1);
} /* usage */